package org.linlinjava.litemall.admin.service;

import ch.qos.logback.core.util.SystemInfo;
import jodd.io.FileUtil;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.linlinjava.litemall.admin.dto.ArticleRecord;
import org.linlinjava.litemall.core.storage.StorageService;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.domain.LitemallArticles;
import org.linlinjava.litemall.db.domain.LitemallOrder;
import org.linlinjava.litemall.db.domain.LitemallStorage;
import org.linlinjava.litemall.db.service.PiccArticlesService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Service
public class AdminArticlesService {
    private final Log logger = LogFactory.getLog(AdminArticlesService.class);
    @Autowired
    PiccArticlesService piccArticlesService;
    @Autowired
    StorageService storageService;

    /**
     * 创建文章记录，里面增加了其它的业务逻辑
     * 1、将正文的前30个字作为摘要；
     * 2、利用已有的静态html，然后copy组装，将正文添加到其body标签内，然后利用storageservice将inputstream存储到
     * storage表中，然后get到这个新的html的url，再保存到文章的数据库中
     * 3、这样就保证了客户端可以取到这个文章的url，并用来直接访问文章页面
     * @param record
     * @return
     */
    @Transactional
    public LitemallArticles create(ArticleRecord record){
        logger.debug("LJF--->enter articles create");
        logger.debug(record.getArticle());
        LitemallArticles article = record.getArticle();
        article.setAddTime(LocalDateTime.now());
        article.setUpdateTime(LocalDateTime.now());

        try {
            Resource resource = new ClassPathResource("templates/example.html");
            //1. 从html模板读出string，然后用字符串方式，替换其中的内容；
            BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream(), "utf-8"));

            String line;
            StringBuilder sb = new StringBuilder();
            while ((line = reader.readLine()) != null) {
                sb.append(line).append('\n');
            }

            String fileString = sb.toString();
            logger.debug(fileString);

            //由于直接appendText会将带有html格式的富文本直接当成纯文本变成div的文字显示。
            //所以在设置body detail的时候，直接用字符串进行转化
            String fileStringNew = fileString.replaceFirst("###detail###", article.getDetail());

            //2. 利用jsoup开源库解析html文件，然后修改elemtnt节点
            //设置title和time元素的值
            Document doc = Jsoup.parse(fileStringNew);
            Element body = doc.body();
            body.getElementById("title").appendText(article.getName());
            body.getElementById("time").appendText(article.getUpdateTime().toString());

            //3. 文章发布时，主体中图片有width和height的属性，让显示格式不正常；
            //现在遍历body中的img元素，将这两个属性去掉
            Elements elems = body.getElementsByTag("img");
            Element elem = null;
            for (int i=0; i< elems.size(); i++){
                elem = elems.get(i);
                if (elem!=null){
                    elem.removeAttr("width");
                    elem.removeAttr("height");
                }
            }

            //4. 从doc中读取第一个纯文字的<p>元素，然后将他的值作为brief
            Elements elemsP = body.getElementsByTag("p");
            String briefString;
            Element elemP = null;
            for (int i=0; i<elemsP.size(); i++){
                elemP = elemsP.get(i);
                if (elemP.getElementsByTag("img")==null) break;
            }
            briefString = elemP.text();
            //如果发布文章时，简介为空，则取正文的前40个文字作为简介
            if (article.getBrief() == null) {
                if (briefString.length() >= 40)
                    briefString = briefString.substring(0, 40);
                article.setBrief(briefString);
            }
            logger.debug(doc.html());

            //4. 创建一个storage资源，并保存到数据库中，将每个文章当成url
            InputStream inputStream = new ByteArrayInputStream(doc.html().getBytes());
            LitemallStorage storage =  storageService.store(inputStream, inputStream.available(), "text/html", article.getName()+".html");

            //5. 将静态网页资源的url，存储到文章记录中，供客户端直接调用
            article.setDetailUrl(storage.getUrl());
        }catch (Exception e){
            e.printStackTrace();
        }

        piccArticlesService.create(article);
        logger.debug("LJF---> after create article: "+article);
        return article;
    }

    /**
     * 返回所有文章的记录表，包含联合查询的storage中的headerUrl type信息
     * @param deleted
     * @param page
     * @param limit
     * @param sort
     * @return
     */
    @Transactional
    public Object list(Integer deleted, Integer page, Integer limit, String sort) {
        List<LitemallArticles> articleList = piccArticlesService.getAllArticles(deleted, page, limit, sort);
        logger.debug("LJF--->articles list: "+articleList);
        return ResponseUtil.okList(articleList);
    }

    @Transactional
    public void delete(Integer id){
        piccArticlesService.delete(id);
        return;
    }

    private String inputStream2String(InputStream is) {
        BufferedReader in = new BufferedReader(new InputStreamReader(is));
        StringBuffer buffer = new StringBuffer();
        String line = "";
        try {
            while ((line = in.readLine()) != null) {
                buffer.append(line);
            }
        }catch (IOException e){
            e.printStackTrace();
        }
        return buffer.toString();
    }
}
